package com.jeeww.core.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 * 类描述:用于查询及使用语句进行数据库操作的DAO.
 * @param <T> 泛型.
 * @param <PK> 主键类型.
 * @author 蒋文武
 */
@Repository
public class BaseDAO<T extends Serializable, PK extends Serializable> implements BaseDAOInterface<T, PK> {
    /**
     * logger.
     */
    private Logger logger = Logger.getLogger(BaseDAO.class);
    /**
     * sessionFactory.
     */
    @Autowired
    private SessionFactory sessionFactory;

    /**
     * @return Session.
     */
    private Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    /**
     * 实体类类型(由构造方法自动赋值).
     */
    private Class<T> entityClass;

    /**
     * 构造方法，根据实例类自动获取实体类类型.
     */
    @SuppressWarnings("unchecked")
    public BaseDAO() {
        this.entityClass = null;
        Class<?> c = (Class<?>) getClass();
        Type t = c.getGenericSuperclass();
        if (t instanceof ParameterizedType) {
            Type[] p = ((ParameterizedType) t).getActualTypeArguments();
            this.entityClass = (Class<T>) p[0];
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public final T get(final PK id) {
        if (logger.isDebugEnabled()) {
            logger.debug("Execute get method: id is " + id);
        }
        return (T) getSession().get(entityClass, id);
    }

    @SuppressWarnings("unchecked")
    @Override
    public final T load(final PK id) {
        return (T) getSession().load(entityClass, id);
    }

    @Override
    public final void update(final T entity) {
        getSession().update(entity);
    }

    @Override
    public final void updateList(final List<T> entityList) {
        for (T obj : entityList) {
            getSession().update(obj);
        }
    }

    @Override
    public final void save(final T entity) {
        getSession().save(entity);
    }

    @Override
    public final void saveList(final List<T> entityList) {
        for (T obj : entityList) {
            getSession().save(obj);
        }
    }

    @Override
    public final void saveOrUpdate(final T entity) {
        getSession().saveOrUpdate(entity);
    }

    @Override
    public final void delete(final T entity) {
        getSession().delete(entity);
    }

    @Override
    public final void deleteByKey(final PK id) {
        getSession().delete(this.load(id));
    }

    @SuppressWarnings("unchecked")
    @Override
    public final List<T> getAll() {
        return getSession().createCriteria(entityClass).setCacheable(true).list();
    }
}
